package com.lyzml.voice;

import android.os.Bundle;
import android.util.Log;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechUtility;
import com.taobao.weex.WXSDKEngine;
import com.taobao.weex.annotation.JSMethod;
import com.taobao.weex.bridge.JSCallback;


public class LyzmlVoiceWXModule extends WXSDKEngine.DestroyableModule {

    private static final String TAG = "LyzmlVoiceWXModule";

    private volatile static SpeechRecognizer instance;

    /**
     * 用于缓存本次识别的所有结果
     */
    private JSONObject iflyResultJson = new JSONObject();

    @Override
    public void destroy() {

    }

    private SpeechRecognizer getInstance() {
        if (instance == null) {
            synchronized (SpeechRecognizer.class) {
                if (instance == null) {
                    instance = SpeechRecognizer.createRecognizer(mWXSDKInstance.getContext(), new InitListener(){
                        @Override
                        public void onInit(int i) {
                            Log.d(TAG,"===getInstance==="+i);
                        }
                    });;
                }
            }
        }
        return instance;
    }

    /**
     * 初始化
     */
    @JSMethod(uiThread = true)
    public void initIFly(JSONObject params, JSCallback callback){
        JSONObject retJson = new JSONObject();
        String appId = params.getString("appId");
        if(appId!=null){
            SpeechUtility speech = SpeechUtility.createUtility(mWXSDKInstance.getContext(), SpeechConstant.APPID +"="+appId);
            if(speech!=null){
                retJson.put("code",0);
                retJson.put("desc","初始化成功");
            }else{
                retJson.put("code",1);
                retJson.put("desc","初始化失败");
            }
        }else{
            retJson.put("code",1);
            retJson.put("desc","参数错误");
        }
        callback.invoke(retJson);
    }

    /**
     * 开始语音听写
     */
    @JSMethod(uiThread = true)
    public void startRecognize(JSONObject params, final JSCallback callback) {
        //初始化识别无UI识别对象
        SpeechRecognizer iFly = getInstance();
        iflyResultJson = new JSONObject(); //清空上次的识别结果
        // 清空参数
        iFly.setParameter(SpeechConstant.PARAMS, null);
        //设置语法ID和 SUBJECT 为空，以免因之前有语法调用而设置了此参数；或直接清空所有参数，具体可参考 DEMO 的示例。
        iFly.setParameter(SpeechConstant.CLOUD_GRAMMAR, null );
        iFly.setParameter(SpeechConstant.SUBJECT, null );
        //设置返回结果格式，目前支持json,xml以及plain 三种格式，其中plain为纯听写文本内容

        iFly.setParameter(SpeechConstant.RESULT_TYPE, "json");
        //此处engineType为“cloud”
        String engineType = params.getString("engineType");
        if(null!=engineType && engineType.length()>0){
            iFly.setParameter(SpeechConstant.ENGINE_TYPE, engineType);
        }else{
            iFly.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
        }
        //设置语音输入语言，zh_cn为简体中文
        String language= params.getString("language");
        if(null!=language && language.length()>0){
            iFly.setParameter(SpeechConstant.LANGUAGE, language);
        }else{
            iFly.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        }

        //设置结果返回语言
        String accent= params.getString("accent");
        if(null!=accent && accent.length()>0){
            iFly.setParameter(SpeechConstant.ACCENT, accent);
        }else{
            iFly.setParameter(SpeechConstant.ACCENT, "mandarin");
        }

        // 设置语音前端点:静音超时时间，单位ms，即用户多长时间不说话则当做超时处理
        //取值范围{1000～10000}
        String vadBos= params.getString("vadBos");
        if(null!=vadBos && vadBos.length()>0){
            iFly.setParameter(SpeechConstant.VAD_BOS, vadBos);
        }else{
            iFly.setParameter(SpeechConstant.VAD_BOS, "3000");
        }

        //设置语音后端点:后端点静音检测时间，单位ms，即用户停止说话多长时间内即认为不再输入，
        //自动停止录音，范围{0~10000}
        String vadEos= params.getString("vadEos");
        if(null!=vadEos && vadEos.length()>0){
            iFly.setParameter(SpeechConstant.VAD_EOS, vadEos);
        }else{
            iFly.setParameter(SpeechConstant.VAD_EOS, "3000");
        }

        //设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        String asrPtt= params.getString("asrPtt");
        if(null!=asrPtt && asrPtt.length()>0){
            iFly.setParameter(SpeechConstant.ASR_PTT, asrPtt);
        }else{
            iFly.setParameter(SpeechConstant.ASR_PTT,"1");
        }

        //开启动态修正
        String asrDwa= params.getString("asrDwa");
        if(null!=asrDwa && asrDwa.length()>0){
            iFly.setParameter(SpeechConstant.ASR_DWA, asrDwa);
        }else{
            iFly.setParameter(SpeechConstant.ASR_DWA,"wpgs");
        }

        //开始识别，并设置监听器
        iFly.startListening(new RecognizerListener() {
            JSONObject retJson = new JSONObject();

            @Override
            public void onVolumeChanged(int i, byte[] bytes) {
//                Log.d(TAG,"=====onVolumeChanged===="+i);
            }

            @Override
            public void onBeginOfSpeech() {
                Log.d(TAG,"=====onBeginOfSpeech====");
                retJson.put("code",0);
                retJson.put("desc","onBeginOfSpeech");
                callback.invokeAndKeepAlive(retJson);
            }

            @Override
            public void onEndOfSpeech() {
                Log.d(TAG,"=====onEndOfSpeech====");
                retJson.put("code",2);
                retJson.put("desc","onEndOfSpeech");
                callback.invokeAndKeepAlive(retJson);
            }

            @Override
            public void onResult(RecognizerResult recognizerResult, boolean b) {
                String retStr = parseIFlyResult(recognizerResult.getResultString());
                retJson.put("code",1);
                retJson.put("desc","onResult");
                retJson.put("result",retStr);
                callback.invokeAndKeepAlive(retJson);
            }

            @Override
            public void onError(SpeechError speechError) {
                Log.d(TAG,"=====onError===="+speechError);
                retJson.put("code",1);
                retJson.put("desc","onResult");
                retJson.put("result",speechError);
                callback.invokeAndKeepAlive(retJson);
            }

            @Override
            public void onEvent(int i, int i1, int i2, Bundle bundle) {
//                Log.d(TAG,"=====onEvent====");
            }
        });
    }

    /**
     * 根据识别结果，从JSON中取出识别出的字句
     * @param jsonStr
     * @return
     */
    private String parseIFlyResult(String jsonStr){
        JSONObject jsonObj = JSONObject.parseObject(jsonStr);
        String sn = jsonObj.getString("sn");
        String pgs = jsonObj.getString("pgs");
        String rg = jsonObj.getString("rg");

        //如果pgs是rpl就在已有的结果中删除掉要覆盖的sn部分
        if ("rpl".equals(pgs)) {
            String[] splitIdxArr = rg.replace("[", "").replace("]", "").split(",");
            int begin = Integer.parseInt(splitIdxArr[0]);
            int end = Integer.parseInt(splitIdxArr[1]);
            for (int i = begin; i <= end; i++) {
                iflyResultJson.remove(i+"");
            }
        }

        iflyResultJson.put(sn, jsonStr);
        StringBuffer resultBuffer = new StringBuffer();
        for (String key : iflyResultJson.keySet()) {
            String valObjStr = iflyResultJson.getString(key);
            resultBuffer.append(getIFlyWords(valObjStr));
        }
        return resultBuffer.toString();
    }

    /**
     * 从识别结果中获取字词
     * @return
     */
    private StringBuffer getIFlyWords(String jsonStr){
        StringBuffer resultBuffer = new StringBuffer();
        JSONObject jsonObj = JSONObject.parseObject(jsonStr);
        JSONArray wsArr = jsonObj.getJSONArray("ws");
        if(wsArr.size()>0){
            for (int i = 0; i < wsArr.size(); i++) {
                JSONObject wordObj = wsArr.getJSONObject(i);
                JSONArray cwArr = wordObj.getJSONArray("cw");
                if(cwArr.size()>0){
                    for (int j = 0; j < cwArr.size(); j++) {
                        JSONObject cwObj = cwArr.getJSONObject(j);
                        String word = cwObj.getString("w");
                        resultBuffer.append(word);
                    }
                }
            }
            return resultBuffer;
        }else{
            return resultBuffer;
        }
    }

    /**
     * 取消听写
     * @param callback
     */
    @JSMethod(uiThread = true)
    public void cancelRecognize(JSCallback callback) {
        SpeechRecognizer iFly = getInstance();
        iFly.cancel();
        if(iFly.isListening()){
            callback.invoke(false);
        }else{
            callback.invoke(true);
        }
    }

    /**
     * 停止听写
     * @param callback
     */
    @JSMethod(uiThread = true)
    public void stopRecognize(JSCallback callback) {
        SpeechRecognizer iFly = getInstance();
        iFly.stopListening();
        if(iFly.isListening()){
            callback.invoke(false);
        }else{
            callback.invoke(true);
        }
    }
}
